#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <functional>

#include "nocopy.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"

enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR
};
static int gsockfd = -1;
static uint16_t gsocknum = 8899;
static std::string testip = "127.0.0.1";


using hander_message_t = std::function<void (int, std::string, InetAddr)>;
// 一般服务器主要是用来进行网络数据读取和写入的，IO的
// 服务器IO逻辑 和 业务逻辑
class UdpServer
{
public:
    UdpServer(hander_message_t func, uint16_t port, std::string localip = testip)
        : _sockfd(gsockfd), _localport(port), _isrunning(false), _hander_message(func),
        _localip(localip)
    //,_localip(localip)
    {
    }
    void Init()
    {
        // 1.创建套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(FATAL, "socket error!\n");
            exit(SOCKET_ERROR);
        }
        LOG(DEBUG, "socket create success! _sockfd=%d\n", _sockfd);

        // 2.绑定IP和端口
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_localport); // 记得大小端转化（也就是本机和网络字节流转化）
        //local.sin_addr.s_addr = inet_addr(_localip.c_str());
        local.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            LOG(FATAL, "bind error!\n");
            exit(BIND_ERROR);
        }
        LOG(DEBUG, "socket bind IP and port success!_port=%d,_localip=%s\n", _localport, _localip.c_str());
    }
    void Start()
    {
        _isrunning = true;
        // 3.接收和传输消息
        char inbuffer[1024];
        while (_isrunning)
        {

            // 收消息
            // 远端信息
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr *)&peer, &len);
            if (n > 0)
            {
                InetAddr addr(peer);
                inbuffer[n] = 0;
                LOG(INFO, "[%s:%d]#%s\n", addr.IP().c_str(), addr.Port(),inbuffer);
                _hander_message(_sockfd, inbuffer, addr);
            }
            else{
                LOG(DEBUG, "recv error!\n");
            }
        }
    }
    ~UdpServer()
    {
    }

private:
    // 给服务器设定回调，用来让上层进行注册业务的处理方法
    hander_message_t _hander_message;
    int _sockfd;
    uint16_t _localport;
    std::string _localip; // 点分十进制
    bool _isrunning;
};


